#include "Auto_Top.h";
#include "Aquarium_Devices.h";

extern LiquidCrystal     lcd;
extern Clock                           clock;
extern Aquarium_Modes   aquarium_modes;

prog_char Auto_Top_Error_0[] PROGMEM = "Auto Top:";
prog_char Auto_Top_Error_1[] PROGMEM = " Not Stop After";
prog_char Auto_Top_Error_2[] PROGMEM = " Sec";
prog_char Auto_Top_Error_3[] PROGMEM = " Pump Turn On";
prog_char Auto_Top_Error_4[] PROGMEM = " Times Today";
prog_char Auto_Top_Error_5[] PROGMEM = " Pump Not Turn On";
prog_char Auto_Top_Error_6[] PROGMEM = "   Today";



PROGMEM const char *Auto_Top_Errors_Table[] = 
{   
  Auto_Top_Error_0,
  Auto_Top_Error_1,
  Auto_Top_Error_2,
  Auto_Top_Error_3,
  Auto_Top_Error_4,
  Auto_Top_Error_5,
  Auto_Top_Error_6
};

byte Auto_Top::Get_Number_Of_Print_Errors(){
  if ( Max_Pump_Time_Error || Max_Number_Of_Time_In_Day_Error || Pump_Did_Not_Turn_Today_Error ){
    return 1+  ((byte)Max_Pump_Time_Error)*2 +  ((byte)Max_Number_Of_Time_In_Day_Error)*2 + ((byte)Pump_Did_Not_Turn_Today_Error)*2;
  }
  return 0;
}

void  Auto_Top::Print_Error(byte Line){
  if ( Line == 0 ){
    strcpy_P(buffer, (char*)pgm_read_word(&(  Auto_Top_Errors_Table[  0 ]     )));
    lcd.print(buffer );
  }
  else {
    byte Line_offset = 0;
    if ( Max_Pump_Time_Error){
      Line_offset = 2;
      if ( Line == 1 ){
        strcpy_P(buffer, (char*)pgm_read_word(&(  Auto_Top_Errors_Table[  1 ]     )));
        lcd.print(buffer );
      }
      if ( Line == 2 ){
        Print_Space(3);
        lcd.print((int)Max_On_Time);
        strcpy_P(buffer, (char*)pgm_read_word(&(  Auto_Top_Errors_Table[  2 ]     )));
        lcd.print(buffer );
      }
    }


    if ( Max_Number_Of_Time_In_Day_Error){
      if ( Line == (1+Line_offset)  ){
        strcpy_P(buffer, (char*)pgm_read_word(&(  Auto_Top_Errors_Table[  3 ]     )));
        lcd.print(buffer );
      }
      if ( Line == (2+Line_offset)  ){
        Print_Space(3);
        lcd.print((int)Number_Of_Time_Pump_On_Today);
        strcpy_P(buffer, (char*)pgm_read_word(&(  Auto_Top_Errors_Table[  4 ]     )));
        lcd.print(buffer );
      }
      Line_offset += 2;
    }

    if (Pump_Did_Not_Turn_Today_Error){
      if ( Line == (1+Line_offset)  ){
        strcpy_P(buffer, (char*)pgm_read_word(&(  Auto_Top_Errors_Table[  5 ]     )));
        lcd.print(buffer );
      }
      if ( Line == (2+Line_offset)  ){
        strcpy_P(buffer, (char*)pgm_read_word(&(  Auto_Top_Errors_Table[  6 ]     )));
        lcd.print(buffer );
      }
      Line_offset += 2;
    }

  }
}


bool Auto_Top::Is_Pump_On(){
  return  !digitalRead(Auto_Top_Pin_IN);
}

void Auto_Top::Turn_Pump_Off(){
   digitalWrite(Auto_Top_Pin_OUT, LOW);    
  //Device_ON_OFF(false, Auto_Top_device_num);
}

void Auto_Top::Turn_Pump_On(){
  digitalWrite(Auto_Top_Pin_OUT, HIGH);    
//  Device_ON_OFF(true, Auto_Top_device_num);
}

void Auto_Top::Turn_Pump_On_Off(){
  if (   Max_Pump_Time_Error ||
    Max_Number_Of_Time_In_Day_Error || 
    !Check_Modes(cur_mode) ){
    Turn_Pump_Off();
  }
  else {
    Turn_Pump_On();
  }
}

void Auto_Top::init(){
  int address = EEPROM_AUTO_TOP_ADDRESS_START;
  pinMode(Auto_Top_Pin_IN, INPUT) ;
  pinMode(Auto_Top_Pin_OUT, OUTPUT);
 
  OnOff = EEPROM.read(address++) ;
  byte Max_On_Time_h = EEPROM.read(address++) ;
  byte Max_On_Time_l = EEPROM.read(address++) ;
  Max_On_Time = word(Max_On_Time_h, Max_On_Time_l) ;
  Max_Number_Of_Time_In_Day= EEPROM.read(address++) ;
  Modes= EEPROM.read(address++) ;

  cur_mode = aquarium_modes.get_Aquarium_mode() ;
  Clear_Errors();

  Turn_Pump_On_Off();
}

void Auto_Top::Save_To_EEPROM(){
  int address = EEPROM_AUTO_TOP_ADDRESS_START;

  EEPROM.write(address++, OnOff) ;
  byte Max_On_Time_h = highByte( Max_On_Time) ;
  EEPROM.write(address++,Max_On_Time_h ) ;
  byte Max_On_Time_l = lowByte( Max_On_Time) ;
  EEPROM.write(address++, Max_On_Time_l) ;
  EEPROM.write(address++, Max_Number_Of_Time_In_Day) ;
  EEPROM.write(address++, Modes) ;

  Turn_Pump_On_Off();

}


void Auto_Top::update(bool new_day){
  byte last_mode = cur_mode;
  cur_mode = aquarium_modes.get_Aquarium_mode() ;

  if ( cur_mode != last_mode ){
    if (  Check_Modes(cur_mode) &&  !Check_Modes(last_mode) ){
      pump_on_min = 250;
    }
    Turn_Pump_On_Off();
  }
  if ( Is_Pump_On() & Check_Modes(cur_mode)  ){
    if ( pump_status ){
      if (   ((int) ( (millis() - Last_time_On ) / 1000 )) > Max_On_Time ){
        Max_Pump_Time_Error = true;
        Turn_Pump_On_Off();        
      }
    } 
    else {
      if ( pump_on_min != clock.get_min() ){
        ++Number_Of_Time_Pump_On_Today;
      }
      Last_time_On = millis() ;
      pump_status = true;
      Is_Pump_on_Today = true;
      pump_on_min = clock.get_min() ;
    }
  }
  else{
    pump_status = false;
  }

  if ( Number_Of_Time_Pump_On_Today > Max_Number_Of_Time_In_Day ) {
    Max_Number_Of_Time_In_Day_Error = true;
    Turn_Pump_On_Off();    
  }

  if ( new_day ){
    if ( !Is_Pump_on_Today ){
      Pump_Did_Not_Turn_Today_Error = true;
    }
    Is_Pump_on_Today = false;
    Number_Of_Time_Pump_On_Today = 0;
  }


}

void Auto_Top::Clear_Errors(){
  Max_Pump_Time_Error = false;
  Max_Number_Of_Time_In_Day_Error = false;
  Pump_Did_Not_Turn_Today_Error = false;

  pump_status = false;
  pump_on_min = 250;

  Is_Pump_on_Today = true;
  Number_Of_Time_Pump_On_Today = 0;  
  Turn_Pump_On_Off();
}

bool Auto_Top::Check_Modes(byte Mode){
  if ( OnOff == true ){
    return bitRead(Modes,Mode ) == 1;// true;//
  }
  return false;
}



































